package com.example.workspace.utils;


import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import com.alibaba.fastjson.JSONObject;
import com.example.workspace.dto.PositionDto;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;



public class MatchImage {
    public static void main(String[] args) {
        String sourceImg = "D:\\image\\test.png";
        String smallImg = "D:\\image\\follow_template.png";
        //new MatchImage().templateMultiMatching(sourceImg, smallImg);

        ToolUtils.loadOpencv();
        List<PositionDto> positionDtos = matchImage(sourceImg, smallImg);
        System.out.println(JSONObject.toJSONString(positionDtos));
    }


    public static List<PositionDto> matchImage(String sourceImg, String templateImg) {

        List<PositionDto> resultList = new ArrayList<>();

        // 2.加载图像
        Mat srcImage = Imgcodecs.imread(sourceImg);//待匹配图片
        Mat templateImage = Imgcodecs.imread(templateImg);// 获取匹配模板1

        // 创建输出图像
        Mat outputImage = new Mat(srcImage.rows(), srcImage.cols(), srcImage.type());

        // 进行模板匹配
        Imgproc.matchTemplate(srcImage, templateImage, outputImage, Imgproc.TM_CCOEFF_NORMED);

        // 设置匹配阈值
        double threshold = 0.8;

        // 循环遍历所有匹配结果
        while (true) {
            // 查找最大匹配值
            Core.MinMaxLocResult result = Core.minMaxLoc(outputImage);
            Point matchLoc = result.maxLoc;
            double maxVal = result.maxVal;

            // 如果匹配值小于阈值，则退出循环
            if (maxVal < threshold) {
                break;
            }

            resultList.add(new PositionDto((int)matchLoc.x, (int)matchLoc.y));
            //System.out.println(matchLoc.x + "," + matchLoc.y);

            // 将匹配位置的值设置为0，以便下一次匹配
            Imgproc.rectangle(outputImage, matchLoc, new Point(matchLoc.x + templateImage.cols(),
                    matchLoc.y + templateImage.rows()), new Scalar(0, 0, 0), -1);
        }
        return resultList;
    }

    public void templateMultiMatching(String sourceImg,String smallImg) {

        // 1.导入Opencv库
        URL url = ClassLoader.getSystemResource("opencv_java481.dll");
        System.load(url.getPath());

        // 2.加载图像
        Mat largeImage = Imgcodecs.imread(sourceImg);//待匹配图片
        Mat smallImage = Imgcodecs.imread(smallImg);// 获取匹配模板1

        // 创建输出图像
        Mat outputImage = new Mat(largeImage.rows(), largeImage.cols(), largeImage.type());

        // 进行模板匹配
        Imgproc.matchTemplate(largeImage, smallImage, outputImage, Imgproc.TM_CCOEFF_NORMED);

        // 设置匹配阈值
        double threshold = 0.8;

        // 循环遍历所有匹配结果
        while (true) {
            // 查找最大匹配值
            Core.MinMaxLocResult result = Core.minMaxLoc(outputImage);
            Point matchLoc = result.maxLoc;
            double maxVal = result.maxVal;

            // 如果匹配值小于阈值，则退出循环
            if (maxVal < threshold) {
                break;
            }

            System.out.println(matchLoc.x + "," + matchLoc.y + " similarity: " + maxVal);

            // 在大图中标出匹配位置
            Imgproc.rectangle(largeImage, matchLoc, new Point(matchLoc.x + smallImage.cols(),
                    matchLoc.y + smallImage.rows()), new Scalar(0, 0, 255), 2);

            // 将匹配位置的值设置为0，以便下一次匹配
            Imgproc.rectangle(outputImage, matchLoc, new Point(matchLoc.x + smallImage.cols(),
                    matchLoc.y + smallImage.rows()), new Scalar(0, 0, 0), -1);
        }

        HighGui.imshow("模板匹配", largeImage);
        HighGui.waitKey();

    }

}
